package com.example.maze.swing;

import com.example.maze.generator.DivisionGenerator;
import com.example.maze.generator.KruskalGenerator;
import com.example.maze.generator.MazeGenerator;
import com.example.maze.model.Maze;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Swing版本的迷宫演示应用程序
 * 支持动画显示寻路过程
 * 
 * @author maze-demo
 */
public class MazeSwingApp extends JFrame {
    private static final Logger logger = LoggerFactory.getLogger(MazeSwingApp.class);
    
    // UI组件
    private MazePanel mazePanel;
    private SwingAnimationController animationController;
    
    // 控制面板组件
    private JTextField widthField;
    private JTextField heightField;
    private JComboBox<String> generatorComboBox;
    private JComboBox<String> algorithmComboBox;
    private JSlider speedSlider;
    private JButton generateButton;
    private JButton startButton;
    private JButton pauseButton;
    private JButton stopButton;
    private JButton resetButton;
    
    // 状态显示组件
    private JLabel statusLabel;
    private JLabel stepLabel;
    private JTextArea resultArea;
    
    // 数据
    private Maze currentMaze;
    private Map<String, AnimatedMazeSolver> solvers;
    private ExecutorService executorService;
    
    public MazeSwingApp() {
        initializeSolvers();
        initializeUI();
        setupEventHandlers();
        
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("迷宫寻路算法动画演示");
        setSize(1200, 800);
        setLocationRelativeTo(null);
        
        // 生成初始迷宫
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                generateMaze();
            }
        });
    }
    
    /**
     * 初始化寻路器
     */
    private void initializeSolvers() {
        solvers = new HashMap<>();
        solvers.put("DFS", new SwingAnimatedDFSSolver());
        solvers.put("BFS", new SwingAnimatedBFSSolver());
        solvers.put("A*", new SwingAnimatedAStarSolver());
        executorService = Executors.newSingleThreadExecutor();
    }
    
    /**
     * 初始化UI组件
     */
    private void initializeUI() {
        // 使用默认外观
        
        // 迷宫显示组件
        mazePanel = new MazePanel();
        animationController = new SwingAnimationController(mazePanel);
        
        // 控制面板组件
        widthField = new JTextField("20", 5);
        heightField = new JTextField("20", 5);
        
        generatorComboBox = new JComboBox<String>(new String[]{"Kruskal", "Division"});
        algorithmComboBox = new JComboBox<String>(new String[]{"DFS", "BFS", "A*"});
        
        speedSlider = new JSlider(10, 1000, 100);
        speedSlider.setMajorTickSpacing(200);
        speedSlider.setMinorTickSpacing(50);
        speedSlider.setPaintTicks(true);
        speedSlider.setPaintLabels(true);
        
        generateButton = new JButton("生成迷宫");
        startButton = new JButton("开始寻路");
        pauseButton = new JButton("暂停");
        stopButton = new JButton("停止");
        resetButton = new JButton("重置");
        
        // 状态显示组件
        statusLabel = new JLabel("就绪");
        stepLabel = new JLabel("等待开始...");
        resultArea = new JTextArea(5, 30);
        resultArea.setEditable(false);
        resultArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
        
        // 布局
        setLayout(new BorderLayout());
        add(createMazeDisplayArea(), BorderLayout.CENTER);
        add(createControlPanel(), BorderLayout.EAST);
        add(createStatusArea(), BorderLayout.SOUTH);
    }
    
    /**
     * 设置事件处理器
     */
    private void setupEventHandlers() {
        generateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                generateMaze();
            }
        });
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startAnimation();
            }
        });
        pauseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pauseAnimation();
            }
        });
        stopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                stopAnimation();
            }
        });
        resetButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                resetMaze();
            }
        });
        
        speedSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            @Override
            public void stateChanged(javax.swing.event.ChangeEvent e) {
                int delay = speedSlider.getValue();
                animationController.setAnimationSpeed(delay);
            }
        });
        
        // 动画控制器事件监听
        animationController.setStateListener(new Consumer<SwingAnimationController.AnimationState>() {
            @Override
            public void accept(SwingAnimationController.AnimationState state) {
                onAnimationStateChanged(state);
            }
        });
        animationController.setStepListener(new Consumer<SolverStep>() {
            @Override
            public void accept(SolverStep step) {
                onAnimationStep(step);
            }
        });
        animationController.setResultListener(new Consumer<AnimatedSolverResult>() {
            @Override
            public void accept(AnimatedSolverResult result) {
                onAnimationResult(result);
            }
        });
    }
    
    /**
     * 创建迷宫显示区域
     */
    private JPanel createMazeDisplayArea() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder("迷宫显示"));
        
        JScrollPane scrollPane = new JScrollPane(mazePanel);
        scrollPane.setPreferredSize(new Dimension(600, 600));
        panel.add(scrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    /**
     * 创建控制面板
     */
    private JPanel createControlPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBorder(BorderFactory.createTitledBorder("控制面板"));
        panel.setPreferredSize(new Dimension(250, 0));
        
        // 迷宫参数
        JPanel mazeParams = new JPanel(new GridBagLayout());
        mazeParams.setBorder(BorderFactory.createTitledBorder("迷宫参数"));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2, 2, 2, 2);
        
        gbc.gridx = 0; gbc.gridy = 0;
        mazeParams.add(new JLabel("宽度:"), gbc);
        gbc.gridx = 1;
        mazeParams.add(widthField, gbc);
        
        gbc.gridx = 0; gbc.gridy = 1;
        mazeParams.add(new JLabel("高度:"), gbc);
        gbc.gridx = 1;
        mazeParams.add(heightField, gbc);
        
        gbc.gridx = 0; gbc.gridy = 2;
        mazeParams.add(new JLabel("生成器:"), gbc);
        gbc.gridx = 1;
        mazeParams.add(generatorComboBox, gbc);
        
        // 寻路参数
        JPanel algorithmParams = new JPanel(new GridBagLayout());
        algorithmParams.setBorder(BorderFactory.createTitledBorder("寻路参数"));
        
        gbc.gridx = 0; gbc.gridy = 0;
        algorithmParams.add(new JLabel("算法:"), gbc);
        gbc.gridx = 1;
        algorithmParams.add(algorithmComboBox, gbc);
        
        gbc.gridx = 0; gbc.gridy = 1;
        algorithmParams.add(new JLabel("速度(ms):"), gbc);
        gbc.gridx = 1; gbc.gridwidth = 2;
        algorithmParams.add(speedSlider, gbc);
        
        // 控制按钮
        JPanel buttons = new JPanel(new GridLayout(5, 1, 5, 5));
        buttons.setBorder(BorderFactory.createTitledBorder("操作控制"));
        buttons.add(generateButton);
        buttons.add(startButton);
        buttons.add(pauseButton);
        buttons.add(stopButton);
        buttons.add(resetButton);
        
        panel.add(mazeParams);
        panel.add(algorithmParams);
        panel.add(buttons);
        panel.add(Box.createVerticalGlue());
        
        return panel;
    }
    
    /**
     * 创建状态显示区域
     */
    private JPanel createStatusArea() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder("状态信息"));
        
        JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        statusPanel.add(new JLabel("状态:"));
        statusPanel.add(statusLabel);
        statusPanel.add(Box.createHorizontalStrut(20));
        statusPanel.add(new JLabel("当前步骤:"));
        statusPanel.add(stepLabel);
        
        JScrollPane resultScrollPane = new JScrollPane(resultArea);
        resultScrollPane.setPreferredSize(new Dimension(0, 120));
        
        panel.add(statusPanel, BorderLayout.NORTH);
        panel.add(resultScrollPane, BorderLayout.CENTER);
        
        return panel;
    }
    
    /**
     * 生成迷宫
     */
    private void generateMaze() {
        try {
            int width = Integer.parseInt(widthField.getText());
            int height = Integer.parseInt(heightField.getText());
            String generatorName = (String) generatorComboBox.getSelectedItem();
            
            if (width < 5 || width > 100 || height < 5 || height > 100) {
                JOptionPane.showMessageDialog(this, "迷宫尺寸必须在5-100之间", "错误", JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            currentMaze = new Maze(height, width);
            MazeGenerator generator = createGenerator(generatorName);
            
            statusLabel.setText("生成迷宫中...");
            
            // 在后台线程生成迷宫
            executorService.execute(() -> {
                try {
                    generator.generate(currentMaze);
                    
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            mazePanel.setMaze(currentMaze);
                            statusLabel.setText("迷宫生成完成");
                            resultArea.setText(String.format("生成了 %dx%d 的迷宫\\n生成器: %s\\n",
                                width, height, generator.getName()));
                        }
                    });
                } catch (Exception e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            statusLabel.setText("生成失败");
                            JOptionPane.showMessageDialog(MazeSwingApp.this, "迷宫生成失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
                        }
                    });
                }
            });
            
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, "请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /**
     * 开始动画
     */
    private void startAnimation() {
        if (currentMaze == null) {
            JOptionPane.showMessageDialog(this, "请先生成迷宫", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        String algorithmName = (String) algorithmComboBox.getSelectedItem();
        AnimatedMazeSolver solver = solvers.get(algorithmName);
        
        if (solver == null) {
            JOptionPane.showMessageDialog(this, "不支持的算法: " + algorithmName, "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        animationController.startAnimation(currentMaze, solver);
    }
    
    /**
     * 暂停动画
     */
    private void pauseAnimation() {
        animationController.pauseAnimation();
    }
    
    /**
     * 停止动画
     */
    private void stopAnimation() {
        animationController.stopAnimation();
    }
    
    /**
     * 重置迷宫
     */
    private void resetMaze() {
        if (animationController.isAnimating()) {
            animationController.stopAnimation();
        }
        
        mazePanel.resetDisplay();
        statusLabel.setText("已重置");
        stepLabel.setText("等待开始...");
        resultArea.setText("");
    }
    
    /**
     * 创建生成器
     */
    private MazeGenerator createGenerator(String name) {
        switch (name) {
            case "Kruskal":
                return new KruskalGenerator();
            case "Division":
                return new DivisionGenerator();
            default:
                return new KruskalGenerator();
        }
    }
    
    /**
     * 动画状态改变事件
     */
    private void onAnimationStateChanged(SwingAnimationController.AnimationState state) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                switch (state) {
                    case RUNNING:
                        statusLabel.setText("寻路中...");
                        startButton.setEnabled(false);
                        pauseButton.setEnabled(true);
                        stopButton.setEnabled(true);
                        generateButton.setEnabled(false);
                        break;
                    case PAUSED:
                        statusLabel.setText("已暂停");
                        startButton.setEnabled(true);
                        pauseButton.setEnabled(false);
                        break;
                    case COMPLETED:
                        statusLabel.setText("寻路完成");
                        resetButtonStates();
                        break;
                    case CANCELLED:
                        statusLabel.setText("已停止");
                        resetButtonStates();
                        break;
                    case IDLE:
                        statusLabel.setText("就绪");
                        resetButtonStates();
                        break;
                }
            }
        });
    }
    
    /**
     * 动画步骤事件
     */
    private void onAnimationStep(SolverStep step) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                stepLabel.setText(step.getDescription());
            }
        });
    }
    
    /**
     * 动画结果事件
     */
    private void onAnimationResult(AnimatedSolverResult result) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                StringBuilder sb = new StringBuilder();
                sb.append(String.format("算法: %s\\n", result.getAlgorithmName()));
                sb.append(String.format("结果: %s\\n", result.isFound() ? "找到路径" : "未找到路径"));
                
                if (result.isFound()) {
                    sb.append(String.format("路径长度: %d\\n", result.getPathLength()));
                }
                
                sb.append(String.format("访问节点: %d\\n", result.getVisitedCells()));
                sb.append(String.format("执行时间: %d ms\\n", result.getTimeMillis()));
                sb.append(String.format("动画步骤: %d\\n", result.getStepCount()));
                
                resultArea.setText(sb.toString());
            }
        });
    }
    
    /**
     * 重置按钮状态
     */
    private void resetButtonStates() {
        startButton.setEnabled(true);
        pauseButton.setEnabled(false);
        stopButton.setEnabled(false);
        generateButton.setEnabled(true);
    }
    
    @Override
    public void dispose() {
        if (executorService != null) {
            executorService.shutdown();
        }
        if (animationController != null) {
            animationController.shutdown();
        }
        super.dispose();
    }
    
    /**
     * 应用程序入口点
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MazeSwingApp().setVisible(true);
            }
        });
    }
}